<?php


namespace chick1993\util;


use Generator;

/**
 * Class CurlMulti
 * @package chick1993\curl
 */
class CurlMulti
{
    static public function get(array $requests, array $options = []): Generator
    {
        $options[CURLOPT_POST] = 0;
        return self::send($requests, $options);
    }

    /**
     * @param array $requests
     *  格式一： [ [ url => '...', data => [], options => [key=>value, ... ] ], ... ] //一个url对应一组option
     *  格式二： [ urls => ['url1','url2', ...], data => [], options => [key=>value, ...] ] // 多个url对应同一组option
     * @param array $options
     * @return Generator
     */
    static public function post(array $requests, array $options = []): Generator
    {
        $options[CURLOPT_POST] = 1;
        return self::send($requests, $options);
    }

    /**
     * @param array $requests
     *  格式一： [ [ url => '...', options => [key=>value, ... ] ], ... ] //一个url对应一组option
     *  格式二： [ urls => ['url1','url2', ...], options => [key=>value, ...] ] // 多个url对应同一组option
     * @param array $options
     * @return Generator
     */
    static public function send(array $requests, array $options = []): Generator
    {
        $reqs = self::getCurl($requests, $options);
        $mch = curl_multi_init();
        foreach ($reqs as $req) {
            $req && curl_multi_add_handle($mch, $req);
        }
        $active = null;
        do {
            $mrc = curl_multi_exec($mch, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);

        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mch) != -1) {
                do {
                    $mrc = curl_multi_exec($mch, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }
        foreach ($reqs as $index => $ch) {
            if (empty($ch)) {
                continue;
            }
            $rt = [];
            $rt['http_code'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $rt['index'] = $index;
            $rt['curl_error'] = curl_error($ch);
            $rt['curl_errno'] = curl_errno($ch);
            $rt['result'] = curl_multi_getcontent($ch);
            curl_multi_remove_handle($mch, $ch);
            curl_close($ch);
            yield $rt;
        }
        curl_multi_close($mch);
    }

    static protected function getCurl($requests, array $options = []): array
    {
        $defOpt = $options + [
                CURLOPT_TIMEOUT => 3,
                CURLOPT_HEADER => 0,
                CURLOPT_SSL_VERIFYPEER => false,//不验证证SSL书
                CURLOPT_SSL_VERIFYHOST => false,//不验证证SSL书
                CURLOPT_RETURNTRANSFER => 1,//以文件流形式返回数据
            ];
        $return = [];
        if (isset($requests['urls'])) {
            $options = !empty($requests['options']) ? $requests['options'] + $defOpt : $defOpt;
            ($options[CURLOPT_POST] > 0 && isset($requests['data'])) && $options[CURLOPT_POSTFIELDS] = $requests['data'];
            foreach ($requests['urls'] as $key => $url) {
                if (empty($url)) {
                    $return[$key] = null;
                } else {
                    $ch = curl_init($url);
                    curl_setopt_array($ch, $options);
                    $return[$key] = $ch;
                }
            }
        } else {
            foreach ($requests as $key => $request) {
                if (empty($request['url'])) {
                    $return[$key] = null;
                } else {
                    $options = !empty($request['options']) ? $request['options'] + $defOpt : $defOpt;
                    ($options[CURLOPT_POST] > 0 && isset($request['data'])) && $options[CURLOPT_POSTFIELDS] = $request['data'];
                    $ch = curl_init($request['url']);
                    curl_setopt_array($ch, $options);
                    $return[$key] = $ch;
                }
            }
        }
        return $return;
    }
}